﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.templates;
using l1cs.server.datatables;
using l1cs.server.serverpackets;
using l1cs.server.model.skill;
using l1cs.server.utils;
using System.Threading;

namespace l1cs.server.model.Instance
{
    public class L1ItemInstance : L1Object
    {
        private static Logger _log = Logger.getLogger( typeof( L1ItemInstance ).FullName );

        private int _count;

        private int _itemId;

        private L1Item _item;

        private bool _isEquipped = false;

        private int _enchantLevel;

        private bool _isIdentified = false;

        private int _durability;

        private int _chargeCount;

        private int _remainingTime;

        private Nullable<DateTime> _lastUsed = null;

        private int _lastWeight;

        private LastStatus _lastStatus;

        private L1PcInstance _pc;

        private bool _isRunning = false;

        private Timer _timer;

        private int _bless;

        private int _attrEnchantKind;

        private int _attrEnchantLevel;

        public L1ItemInstance()
        {
            _count = 1;
            _enchantLevel = 0;
            _lastStatus = new LastStatus( this );
        }

        public L1ItemInstance( L1Item item, int count )
            : base()
        {
            setItem( item );
            setCount( count );
            _lastStatus = new LastStatus( this );
        }

        /*
         * アイテムが確認(鑑定)済みであるかを返す。
         * 
         * @return 確認済みならtrue、未確認ならfalse。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool isIdentified()
        {
            return _isIdentified;
        }

        /*
         * アイテムが確認(鑑定)済みであるかを設定する。
         * 
         * @param identified
         *            確認済みならtrue、未確認ならfalse。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <param name="identified"></param>
        public void setIdentified( bool identified )
        {
            _isIdentified = identified;
        }

        public String getName()
        {
            return _item.getName();
        }

        /// <summary>
        /// アイテムの個数を返す。
        /// </summary>
        /// <returns></returns>
        public int getCount()
        {/*TTOK*/
            return _count;
        }

        /// <summary>
        /// アイテムの個数を設定する。
        /// </summary>
        /// <param name="count">アイテムの個数</param>
        public void setCount( int count )
        {/*TTOK*/
            _count = count;
        }

        /*
         * アイテムが装備されているかを返す。
         * 
         * @return アイテムが装備されていればtrue、装備されていなければfalse。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool isEquipped()
        {
            return _isEquipped;
        }

        /*
         * アイテムが装備されているかを設定する。
         * 
         * @param equipped
         *            アイテムが装備されていればtrue,装備されていなければfalse。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <param name="equipped"></param>
        public void setEquipped( bool equipped )
        {
            _isEquipped = equipped;
        }

        /// <summary>
        /// L1Itemクラスを返す。
        /// </summary>
        /// <returns></returns>
        public L1Item getItem()
        {/*TTOK*/
            return _item;
        }

        public void setItem( L1Item item )
        {
            _item = item;
            _itemId = item.getItemId();
        }

        public int getItemId()
        {
            return _itemId;
        }

        public void setItemId( int itemId )
        {
            _itemId = itemId;
        }

        public bool isStackable()
        {
            return _item.isStackable();
        }

        override public void onAction( L1PcInstance player ) { }

        public int getEnchantLevel()
        {
            return _enchantLevel;
        }

        public void setEnchantLevel( int enchantLevel )
        {
            _enchantLevel = enchantLevel;
        }

        public int get_gfxid()
        {
            return _item.getGfxId();
        }

        public int get_durability()
        {
            return _durability;
        }

        public int getChargeCount()
        {
            return _chargeCount;
        }

        public void setChargeCount( int i )
        {/*TTOK*/
            _chargeCount = i;
        }

        public int getRemainingTime()
        {
            return _remainingTime;
        }

        /// <summary>
        /// 存在する時間を設定する。
        /// </summary>
        /// <param name="i"></param>
        public void setRemainingTime( int i )
        {
            _remainingTime = i;
        }

        public void setLastUsed( Nullable<DateTime> t )
        {
            _lastUsed = t;
        }

        public Nullable<DateTime> getLastUsed()
        {
            return _lastUsed;
        }

        public int getLastWeight()
        {
            return _lastWeight;
        }

        public void setLastWeight( int weight )
        {
            _lastWeight = weight;
        }

        /// <summary>
        /// 祝福状態を設定する。
        /// </summary>
        /// <param name="i"></param>
        public void setBless( int i )
        {/*TTOK*/
            _bless = i;
        }

        public int getBless()
        {
            return _bless;
        }

        public void setAttrEnchantKind( int i )
        {
            _attrEnchantKind = i;
        }

        public int getAttrEnchantKind()
        {
            return _attrEnchantKind;
        }

        public void setAttrEnchantLevel( int i )
        {
            _attrEnchantLevel = i;
        }

        public int getAttrEnchantLevel()
        {
            return _attrEnchantLevel;
        }

        public int getMr()
        {
            int mr = _item.get_mdef();
            if ( getItemId() == 20011 || getItemId() == 20110
                    || getItemId() == 21108 || getItemId() == 120011 )
            {
                mr += getEnchantLevel();
            }
            if ( getItemId() == 20056 || getItemId() == 120056
                    || getItemId() == 220056 )
            {
                mr += getEnchantLevel() * 2;
            }
            return mr;
        }

        /*
         * 耐久性、0~127まで -の値は許可しない。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <param name="i"></param>
        public void set_durability( int i )
        {
            if ( i < 0 )
            {
                i = 0;
            }

            if ( i > 127 )
            {
                i = 127;
            }
            _durability = i;
        }

        public int getWeight()
        {
            if ( getItem().getWeight() == 0 )
            {
                return 0;
            }
            else
            {
                return Math.Max( getCount() * getItem().getWeight() / 1000, 1 );
            }
        }


        /*
         * 前回DBへ保存した際のアイテムのステータスを格納するクラス
         */
        /// <summary>
        /// 
        /// </summary>
        public class LastStatus
        {
            public int count;

            public int itemId;

            public bool isEquipped = false;

            public int enchantLevel;

            public bool isIdentified = true;

            public int durability;

            public int chargeCount;

            public int remainingTime;

            public Nullable<DateTime> lastUsed;

            public int bless;

            public int attrEnchantKind;

            public int attrEnchantLevel;

            L1ItemInstance cl;

            public LastStatus( L1ItemInstance l1object )
            {
                cl = l1object;
            }
            public void updateAll()
            {
                count = cl.getCount();
                itemId = cl.getItemId();
                isEquipped = cl.isEquipped();
                isIdentified = cl.isIdentified();
                enchantLevel = cl.getEnchantLevel();
                durability = cl.get_durability();
                chargeCount = cl.getChargeCount();
                remainingTime = cl.getRemainingTime();
                lastUsed = cl.getLastUsed();
                bless = cl.getBless();
                attrEnchantKind = cl.getAttrEnchantKind();
                attrEnchantLevel = cl.getAttrEnchantLevel();
            }

            public void updateCount()
            {
                count = cl.getCount();
            }

            public void updateItemId()
            {
                itemId = cl.getItemId();
            }

            public void updateEquipped()
            {
                isEquipped = cl.isEquipped();
            }

            public void updateIdentified()
            {
                isIdentified = cl.isIdentified();
            }

            public void updateEnchantLevel()
            {
                enchantLevel = cl.getEnchantLevel();
            }

            public void updateDuraility()
            {
                durability = cl.get_durability();
            }

            public void updateChargeCount()
            {
                chargeCount = cl.getChargeCount();
            }

            public void updateRemainingTime()
            {
                remainingTime = cl.getRemainingTime();
            }

            public void updateLastUsed()
            {
                lastUsed = cl.getLastUsed();
            }

            public void updateBless()
            {
                bless = cl.getBless();
            }

            public void updateAttrEnchantKind()
            {
                attrEnchantKind = cl.getAttrEnchantKind();
            }

            public void updateAttrEnchantLevel()
            {
                attrEnchantLevel = cl.getAttrEnchantLevel();
            }
        }

        public LastStatus getLastStatus()
        {
            return _lastStatus;
        }

        /*
         * 前回DBに保存した時から変化しているカラムをビット集合として返す。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public int getRecordingColumns()
        {
            int column = 0;

            if ( getCount() != _lastStatus.count )
            {
                column += L1PcInventory.COL_COUNT;
            }
            if ( getItemId() != _lastStatus.itemId )
            {
                column += L1PcInventory.COL_ITEMID;
            }
            if ( isEquipped() != _lastStatus.isEquipped )
            {
                column += L1PcInventory.COL_EQUIPPED;
            }
            if ( getEnchantLevel() != _lastStatus.enchantLevel )
            {
                column += L1PcInventory.COL_ENCHANTLVL;
            }
            if ( get_durability() != _lastStatus.durability )
            {
                column += L1PcInventory.COL_DURABILITY;
            }
            if ( getChargeCount() != _lastStatus.chargeCount )
            {
                column += L1PcInventory.COL_CHARGE_COUNT;
            }
            if ( getLastUsed() != _lastStatus.lastUsed )
            {
                column += L1PcInventory.COL_DELAY_EFFECT;
            }
            if ( isIdentified() != _lastStatus.isIdentified )
            {
                column += L1PcInventory.COL_IS_ID;
            }
            if ( getRemainingTime() != _lastStatus.remainingTime )
            {
                column += L1PcInventory.COL_REMAINING_TIME;
            }
            if ( getBless() != _lastStatus.bless )
            {
                column += L1PcInventory.COL_BLESS;
            }
            if ( getAttrEnchantKind() != _lastStatus.attrEnchantKind )
            {
                column += L1PcInventory.COL_ATTR_ENCHANT_KIND;
            }
            if ( getAttrEnchantLevel() != _lastStatus.attrEnchantLevel )
            {
                column += L1PcInventory.COL_ATTR_ENCHANT_LEVEL;
            }

            return column;
        }

        /*
         * 鞄や倉庫で表示される形式の名前を個数を指定して取得する。<br>
         */
        /// <summary>
        /// 
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public String getNumberedViewName( int count )
        {
            StringBuilder name = new StringBuilder( getNumberedName( count ) );
            int itemType2 = getItem().getType2();
            int itemId = getItem().getItemId();

            if ( itemId == 40314 || itemId == 40316 )
            { // ペットのアミュレット
                L1Pet pet = PetTable.getInstance().getTemplate( getId() );
                if ( pet != null )
                {
                    L1Npc npc = NpcTable.getInstance().getTemplate( pet.get_npcid() );
                    // name.append("[Lv." + pet.get_level() + " "
                    // + npc.get_nameid() + "]");
                    name.Append( "[Lv." + pet.get_level() + " " + pet.get_name() + "]HP" + pet.get_hp() + " " + npc.get_nameid() );
                }
            }

            if ( getItem().getType2() == 0 && getItem().getType() == 2 )
            { // light系アイテム
                if ( isNowLighting() )
                {
                    name.Append( " ($10)" );
                }
                if ( itemId == 40001 || itemId == 40002 )
                { // ランプorランタン
                    if ( getRemainingTime() <= 0 )
                    {
                        name.Append( " ($11)" );
                    }
                }
            }

            if ( isEquipped() )
            {
                if ( itemType2 == 1 )
                {
                    name.Append( " ($9)" ); // 装備(Armed)
                }
                else if ( itemType2 == 2 )
                {
                    name.Append( " ($117)" ); // 装備(Worn)
                }
                else if ( itemType2 == 0 && getItem().getType() == 11 )
                { // petitem
                    name.Append( " ($117)" ); // 装備(Worn)
                }
            }
            return name.ToString();
        }

        /*
         * 鞄や倉庫で表示される形式の名前を返す。<br>
         * 例:+10 カタナ (装備)
         */
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public String getViewName()
        {
            return getNumberedViewName( _count );
        }

        /*
         * ログに表示される形式の名前を返す。<br>
         * 例:アデナ(250) / +6 ダガー
         */
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public String getLogName()
        {
            return getNumberedName( _count );
        }

        /*
         * ログに表示される形式の名前を、個数を指定して取得する。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public String getNumberedName( int count )
        {
            StringBuilder name = new StringBuilder();

            if ( isIdentified() )
            {
                if ( getItem().getType2() == 1 )
                { // 武器
                    int attrEnchantLevel = getAttrEnchantLevel();
                    if ( attrEnchantLevel > 0 )
                    {
                        String attrStr = null;
                        switch ( getAttrEnchantKind() )
                        {
                            case 1: // 地
                                if ( attrEnchantLevel == 1 )
                                {
                                    attrStr = "$6124";
                                }
                                else if ( attrEnchantLevel == 2 )
                                {
                                    attrStr = "$6125";
                                }
                                else if ( attrEnchantLevel == 3 )
                                {
                                    attrStr = "$6126";
                                }
                                break;
                            case 2: // 火
                                if ( attrEnchantLevel == 1 )
                                {
                                    attrStr = "$6115";
                                }
                                else if ( attrEnchantLevel == 2 )
                                {
                                    attrStr = "$6116";
                                }
                                else if ( attrEnchantLevel == 3 )
                                {
                                    attrStr = "$6117";
                                }
                                break;
                            case 4: // 水
                                if ( attrEnchantLevel == 1 )
                                {
                                    attrStr = "$6118";
                                }
                                else if ( attrEnchantLevel == 2 )
                                {
                                    attrStr = "$6119";
                                }
                                else if ( attrEnchantLevel == 3 )
                                {
                                    attrStr = "$6120";
                                }
                                break;
                            case 8: // 風
                                if ( attrEnchantLevel == 1 )
                                {
                                    attrStr = "$6121";
                                }
                                else if ( attrEnchantLevel == 2 )
                                {
                                    attrStr = "$6122";
                                }
                                else if ( attrEnchantLevel == 3 )
                                {
                                    attrStr = "$6123";
                                }
                                break;
                            default:
                                break;
                        }
                        name.Append( attrStr + " " );
                    }
                }
                if ( getItem().getType2() == 1 || getItem().getType2() == 2 )
                { // 武器・防具
                    if ( getEnchantLevel() >= 0 )
                    {
                        name.Append( "+" + getEnchantLevel() + " " );
                    }
                    else if ( getEnchantLevel() < 0 )
                    {
                        name.Append( Convert.ToString( getEnchantLevel() ) + " " );
                    }
                }
            }
            if ( isIdentified() )
            {
                name.Append( _item.getIdentifiedNameId() );
            }
            else
            {
                name.Append( _item.getUnidentifiedNameId() );
            }
            if ( isIdentified() )
            {
                if ( getItem().getMaxChargeCount() > 0 )
                {
                    name.Append( " (" + getChargeCount() + ")" );
                }
                if ( getItem().getItemId() == 20383 )
                { // 騎馬用ヘルム
                    name.Append( " (" + getChargeCount() + ")" );
                }
                if ( getItem().getMaxUseTime() > 0 && getItem().getType2() != 0 )
                { // 武器防具で使用時間制限あり
                    name.Append( " (" + getRemainingTime() + ")" );
                }
            }

            if ( count > 1 )
            {
                name.Append( " (" + count + ")" );
            }

            return name.ToString();
        }

        /*
         * アイテムの状態からサーバーパケットで利用する形式のバイト列を生成し、返す。
         */
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public byte[] getStatusBytes()
        {
            int itemType2 = getItem().getType2();
            int itemId = getItemId();
            BinaryOutputStream os = new BinaryOutputStream();

            if ( itemType2 == 0 )
            { // etcitem
                switch ( getItem().getType() )
                {
                    case 2: // light
                        os.writeC( 22 ); // 明るさ
                        os.writeH( getItem().getLightRange() );
                        break;
                    case 7: // food
                        os.writeC( 21 );
                        // 栄養
                        os.writeH( getItem().getFoodVolume() );
                        break;
                    case 0: // arrow
                    case 15: // sting
                        os.writeC( 1 ); // 打撃値
                        os.writeC( getItem().getDmgSmall() );
                        os.writeC( getItem().getDmgLarge() );
                        break;
                    default:
                        os.writeC( 23 ); // 材質
                        break;
                }
                os.writeC( getItem().getMaterial() );
                os.writeD( getWeight() );

            }
            else if ( itemType2 == 1 || itemType2 == 2 )
            { // weapon | armor
                if ( itemType2 == 1 )
                { // weapon
                    // 打撃値
                    os.writeC( 1 );
                    os.writeC( getItem().getDmgSmall() );
                    os.writeC( getItem().getDmgLarge() );
                    os.writeC( getItem().getMaterial() );
                    os.writeD( getWeight() );
                }
                else if ( itemType2 == 2 )
                { // armor
                    // AC
                    os.writeC( 19 );
                    int ac = ( (L1Armor)getItem() ).get_ac();
                    if ( ac < 0 )
                    {
                        ac = ac - ac - ac;
                    }
                    os.writeC( ac );
                    os.writeC( getItem().getMaterial() );
                    os.writeD( getWeight() );
                }
                // 強化数
                if ( getEnchantLevel() != 0 )
                {
                    os.writeC( 2 );
                    os.writeC( getEnchantLevel() );
                }
                // 損傷度
                if ( get_durability() != 0 )
                {
                    os.writeC( 3 );
                    os.writeC( get_durability() );
                }
                // 両手武器
                if ( getItem().isTwohandedWeapon() )
                {
                    os.writeC( 4 );
                }
                // 攻撃成功
                if ( itemType2 == 1 )
                { // weapon
                    if ( getItem().getHitModifier() != 0 )
                    {
                        os.writeC( 5 );
                        os.writeC( getItem().getHitModifier() );
                    }
                }
                else if ( itemType2 == 2 )
                { // armor
                    if ( getItem().getHitModifierByArmor() != 0 )
                    {
                        os.writeC( 5 );
                        os.writeC( getItem().getHitModifierByArmor() );
                    }
                }
                // 追加打撃
                if ( itemType2 == 1 )
                { // weapon
                    if ( getItem().getDmgModifier() != 0 )
                    {
                        os.writeC( 6 );
                        os.writeC( getItem().getDmgModifier() );
                    }
                }
                else if ( itemType2 == 2 )
                { // armor
                    if ( getItem().getDmgModifierByArmor() != 0 )
                    {
                        os.writeC( 6 );
                        os.writeC( getItem().getDmgModifierByArmor() );
                    }
                }
                // 使用可能
                int bit = 0;
                bit |= getItem().isUseRoyal() ? 1 : 0;
                bit |= getItem().isUseKnight() ? 2 : 0;
                bit |= getItem().isUseElf() ? 4 : 0;
                bit |= getItem().isUseMage() ? 8 : 0;
                bit |= getItem().isUseDarkelf() ? 16 : 0;
                bit |= getItem().isUseDragonknight() ? 32 : 0;
                bit |= getItem().isUseIllusionist() ? 64 : 0;
                // bit |= getItem().isUseHiPet() ? 64 : 0; // ハイペット
                os.writeC( 7 );
                os.writeC( bit );
                // 弓の命中率補正
                if ( getItem().getBowHitModifierByArmor() != 0 )
                {
                    os.writeC( 24 );
                    os.writeC( getItem().getBowHitModifierByArmor() );
                }
                // 弓のダメージ補正
                if ( getItem().getBowDmgModifierByArmor() != 0 )
                {
                    os.writeC( 35 );
                    os.writeC( getItem().getBowDmgModifierByArmor() );
                }
                // MP吸収
                if ( itemId == 126 || itemId == 127 )
                { // マナスタッフ、鋼鉄のマナスタッフ
                    os.writeC( 16 );
                }
                // HP吸収
                if ( itemId == 262 )
                { // ディストラクション
                    os.writeC( 34 );
                }
                // STR~CHA
                if ( getItem().get_addstr() != 0 )
                {
                    os.writeC( 8 );
                    os.writeC( getItem().get_addstr() );
                }
                if ( getItem().get_adddex() != 0 )
                {
                    os.writeC( 9 );
                    os.writeC( getItem().get_adddex() );
                }
                if ( getItem().get_addcon() != 0 )
                {
                    os.writeC( 10 );
                    os.writeC( getItem().get_addcon() );
                }
                if ( getItem().get_addwis() != 0 )
                {
                    os.writeC( 11 );
                    os.writeC( getItem().get_addwis() );
                }
                if ( getItem().get_addint() != 0 )
                {
                    os.writeC( 12 );
                    os.writeC( getItem().get_addint() );
                }
                if ( getItem().get_addcha() != 0 )
                {
                    os.writeC( 13 );
                    os.writeC( getItem().get_addcha() );
                }
                // HP, MP
                if ( getItem().get_addhp() != 0 )
                {
                    os.writeC( 14 );
                    os.writeH( getItem().get_addhp() );
                }
                if ( getItem().get_addmp() != 0 )
                {
                    os.writeC( 32 );
                    os.writeC( getItem().get_addmp() );
                }
                // MR
                if ( getMr() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getMr() );
                }
                // SP(魔力)
                if ( getItem().get_addsp() != 0 )
                {
                    os.writeC( 17 );
                    os.writeC( getItem().get_addsp() );
                }
                // ヘイスト
                if ( getItem().isHasteItem() )
                {
                    os.writeC( 18 );
                }
                // 火の属性
                if ( getItem().get_defense_fire() != 0 )
                {
                    os.writeC( 27 );
                    os.writeC( getItem().get_defense_fire() );
                }
                // 水の属性
                if ( getItem().get_defense_water() != 0 )
                {
                    os.writeC( 28 );
                    os.writeC( getItem().get_defense_water() );
                }
                // 風の属性
                if ( getItem().get_defense_wind() != 0 )
                {
                    os.writeC( 29 );
                    os.writeC( getItem().get_defense_wind() );
                }
                // 地の属性
                if ( getItem().get_defense_earth() != 0 )
                {
                    os.writeC( 30 );
                    os.writeC( getItem().get_defense_earth() );
                }
                // 凍結耐性
                if ( getItem().get_regist_freeze() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getItem().get_regist_freeze() );
                    os.writeC( 33 );
                    os.writeC( 1 );
                }
                // 石化耐性
                if ( getItem().get_regist_stone() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getItem().get_regist_stone() );
                    os.writeC( 33 );
                    os.writeC( 2 );
                }
                // 睡眠耐性
                if ( getItem().get_regist_sleep() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getItem().get_regist_sleep() );
                    os.writeC( 33 );
                    os.writeC( 3 );
                }
                // 暗闇耐性
                if ( getItem().get_regist_blind() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getItem().get_regist_blind() );
                    os.writeC( 33 );
                    os.writeC( 4 );
                }
                // スタン耐性
                if ( getItem().get_regist_stun() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getItem().get_regist_stun() );
                    os.writeC( 33 );
                    os.writeC( 5 );
                }
                // ホールド耐性
                if ( getItem().get_regist_sustain() != 0 )
                {
                    os.writeC( 15 );
                    os.writeH( getItem().get_regist_sustain() );
                    os.writeC( 33 );
                    os.writeC( 6 );
                }
                // 幸運
                // if (getItem.getLuck() != 0) {
                // os.writeC(20);
                // os.writeC(val);
                // }
                // 種類
                // if (getItem.getDesc() != 0) {
                // os.writeC(25);
                // os.writeH(val); // desc.tbl ID
                // }
                // レベル
                // if (getItem.getLevel() != 0) {
                // os.writeC(26);
                // os.writeH(val);
                // }
            }
            return os.getBytes();
        }

        //class EnchantTimer
        //{
        //    public EnchantTimer()
        //    {
        //    }
        //    public void cancel() { }
        public void EnchantTimerSub( object state )
        {
            int type = getItem().getType();
            int type2 = getItem().getType2();
            int itemId = getItem().getItemId();
            if ( _pc != null && _pc.getInventory().checkItem( itemId ) )
            {
                if ( type == 2 && type2 == 2 && isEquipped() )
                {
                    _pc.addAc( 3 );
                    _pc.sendPackets( new S_OwnCharStatus( _pc ) );
                }
            }
            setAcByMagic( 0 );
            setDmgByMagic( 0 );
            setHolyDmgByMagic( 0 );
            setHitByMagic( 0 );
            _pc.sendPackets( new S_ServerMessage( 308, getLogName() ) );
            _isRunning = false;
            _timer = null;
        }
        //}

        private int _acByMagic = 0;

        public int getAcByMagic()
        {
            return _acByMagic;
        }

        public void setAcByMagic( int i )
        {
            _acByMagic = i;
        }

        private int _dmgByMagic = 0;

        public int getDmgByMagic()
        {
            return _dmgByMagic;
        }

        public void setDmgByMagic( int i )
        {
            _dmgByMagic = i;
        }

        private int _holyDmgByMagic = 0;

        public int getHolyDmgByMagic()
        {
            return _holyDmgByMagic;
        }

        public void setHolyDmgByMagic( int i )
        {
            _holyDmgByMagic = i;
        }

        private int _hitByMagic = 0;

        public int getHitByMagic()
        {
            return _hitByMagic;
        }

        public void setHitByMagic( int i )
        {
            _hitByMagic = i;
        }

        public void setSkillArmorEnchant( L1PcInstance pc, int skillId, int skillTime )
        {
            int type = getItem().getType();
            int type2 = getItem().getType2();
            if ( _isRunning )
            {
                _timer.Dispose();
                int itemId = getItem().getItemId();
                if ( pc != null && pc.getInventory().checkItem( itemId ) )
                {
                    if ( type == 2 && type2 == 2 && isEquipped() )
                    {
                        pc.addAc( 3 );
                        pc.sendPackets( new S_OwnCharStatus( pc ) );
                    }
                }
                setAcByMagic( 0 );
                _isRunning = false;
                _timer = null;
            }

            if ( type == 2 && type2 == 2 && isEquipped() )
            {
                pc.addAc( -3 );
                pc.sendPackets( new S_OwnCharStatus( pc ) );
            }
            setAcByMagic( 3 );
            _pc = pc;
            // TODO 優先度9 タイマースレッド
            //_timer = new EnchantTimer();
            //(new Timer()).schedule(_timer, skillTime);
            _timer = new Timer( new TimerCallback( EnchantTimerSub ), null, skillTime, Timeout.Infinite );
            _isRunning = true;
        }

        public void setSkillWeaponEnchant( L1PcInstance pc, int skillId,
                int skillTime )
        {
            if ( getItem().getType2() != 1 )
            {
                return;
            }
            if ( _isRunning )
            {
                _timer.Dispose();
                setDmgByMagic( 0 );
                setHolyDmgByMagic( 0 );
                setHitByMagic( 0 );
                _isRunning = false;
                _timer = null;
            }

            switch ( skillId )
            {
                case L1SkillId.HOLY_WEAPON:
                    setHolyDmgByMagic( 1 );
                    setHitByMagic( 1 );
                    break;

                case L1SkillId.ENCHANT_WEAPON:
                    setDmgByMagic( 2 );
                    break;

                case L1SkillId.BLESS_WEAPON:
                    setDmgByMagic( 2 );
                    setHitByMagic( 2 );
                    break;

                case L1SkillId.SHADOW_FANG:
                    setDmgByMagic( 5 );
                    break;

                default:
                    break;
            }

            _pc = pc;
            // TODO 優先度9 タイマースレッド
            //_timer = new EnchantTimer();
            //(new Timer()).schedule(_timer, skillTime);
            _timer = new Timer( new TimerCallback( EnchantTimerSub ), null, skillTime, Timeout.Infinite );
            _isRunning = true;
        }

        private int _itemOwnerId = 0;

        public int getItemOwnerId()
        {
            return _itemOwnerId;
        }

        public void setItemOwnerId( int i )
        {
            _itemOwnerId = i;
        }

        public void startItemOwnerTimer( L1PcInstance pc )
        {
            setItemOwnerId( pc.getId() );
            //L1ItemOwnerTimer timer = new L1ItemOwnerTimer( this, 10000 );
            //timer.begin();
            ItemOwnerTimer = new Timer( new TimerCallback( L1ItemOwnerTimerSub ), null, 10000, Timeout.Infinite );
        }
        Timer ItemOwnerTimer;
        public void L1ItemOwnerTimerSub( object state )
        {
            setItemOwnerId( 0 );
            ItemOwnerTimer.Dispose();
        }

        public void L1EquipmentTimerSub( object state )
        {
            L1PcInstance _pc = (L1PcInstance)state;
            if ( ( getRemainingTime() - 1 ) > 0 )
            {
                setRemainingTime( getRemainingTime() - 1 );
                _pc.getInventory().updateItem( this, L1PcInventory.COL_REMAINING_TIME );
            }
            else
            {
                _pc.getInventory().removeItem( this, 1 );
                _equipmentTimer.Dispose();
            }
        }

        private Timer _equipmentTimer;

        public void startEquipmentTimer( L1PcInstance pc )
        {
            if ( getRemainingTime() > 0 )
            {
                // TODO 優先度9 タイマースレッド
                //_equipmentTimer = new L1EquipmentTimer( pc, this, 1000, 1000 );
                //Timer timer = new Timer( true );
                //timer.scheduleAtFixedRate( _equipmentTimer, 1000, 1000 );
                //ThreadPool.QueueUserWorkItem( new WaitCallback( _equipmentTimer.run ) );
                _equipmentTimer = new Timer( new TimerCallback( L1EquipmentTimerSub ), pc, 1000, 1000 );
            }
        }

        public void stopEquipmentTimer( L1PcInstance pc )
        {
            if ( getRemainingTime() > 0 )
            {
                // TODO 優先度9 タイマースレッドの停止
                //_equipmentTimer.cancel();
                //_equipmentTimer = null;
                _equipmentTimer.Dispose();
                _equipmentTimer = null;
            }
        }

        private bool _isNowLighting = false;

        public bool isNowLighting()
        {
            return _isNowLighting;
        }

        public void setNowLighting( bool flag )
        {
            _isNowLighting = flag;
        }
    }
}
